#include "mkvmuxfilter.hpp"
#include "mkvstreamaudioac3.hpp"
#include "mkvstreamaudiovorbis.hpp"
#include "vorbistypes.hpp"
#include <uuids.h>
#include <vfwmsgs.h>
#include <cassert>

namespace MkvMux
{

InpinAudio::InpinAudio(Filter* p) :
    Inpin(p, L"audio")
{
    CMediaTypes& mtv = m_preferred;
    
    MkvStreamAudioAc3::GetMediaTypes(mtv);
    MkvStreamAudioVorbis::GetMediaTypes(mtv);
}


InpinAudio::~InpinAudio()
{
}


HRESULT InpinAudio::QueryAccept(const AM_MEDIA_TYPE* pmt)
{
    if (pmt == 0)
        return E_INVALIDARG;
    
    const AM_MEDIA_TYPE& mt = *pmt;
    
    if (MkvStreamAudioAc3::QueryAccept(mt))
        return S_OK;
        
    if (MkvStreamAudioVorbis::QueryAccept(mt))
        return S_OK;

    return S_FALSE;
}


HRESULT InpinAudio::GetAllocatorRequirements(ALLOCATOR_PROPERTIES* p)
{
    if (p == 0)
        return E_POINTER;
        
    assert(m_connection);
    assert(!m_connection_mt.Empty());

    const AM_MEDIA_TYPE& mt = m_connection_mt[0];
    ALLOCATOR_PROPERTIES& props = *p;
    
    if (mt.subtype == MEDIASUBTYPE_DOLBY_AC3)
        return MkvStreamAudioAc3::GetAllocatorRequirements(mt, props);
        
    if (mt.subtype == VorbisTypes::MEDIASUBTYPE_VORBIS2_AUDIO)
        return MkvStreamAudioVorbis::GetAllocatorRequirements(mt, props);
        
    return VFW_E_NOT_CONNECTED;
}



HRESULT InpinAudio::OnInit()
{
    assert(m_connection);
    assert(!m_connection_mt.Empty());

    MkvContext& ctx = m_pFilter->m_mkv;
    const AM_MEDIA_TYPE& mt = m_connection_mt[0];
    
    MkvStreamAudio* pStream;

    if (mt.subtype == MEDIASUBTYPE_DOLBY_AC3)
        pStream = MkvStreamAudioAc3::CreateStream(ctx, mt);
        
    else if (mt.subtype == VorbisTypes::MEDIASUBTYPE_VORBIS2_AUDIO)
        pStream = MkvStreamAudioVorbis::CreateStream(ctx, mt);
        
    else        
        return VFW_E_NOT_CONNECTED;
   
    ctx.SetAudio(pStream);  //TODO: accept multiple audio streams
    m_pStream = pStream;

    return S_OK;
}


void InpinAudio::OnFinal()
{
   MkvContext& ctx = m_pFilter->m_mkv;
   ctx.SetAudio(0);
}


HANDLE InpinAudio::GetOtherHandle() const
{
    const InpinVideo& iv = m_pFilter->m_inpin_video;    
    return iv.m_hSample;
}



} //end namespace MkvMux
